package org.example.aspect;


import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.example.annotation.HasPermission;
import org.example.dao.dto.user.UserDto;
import org.example.exception.AuthException;
import org.example.exception.ServerErrorException;
import org.example.skytool.commom.ContextUtil;
import org.example.utils.oaa.RedisOaaService;
import org.example.utils.user.RedisUserService;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * @author 22449
 */
@Component
@Aspect
@Slf4j
public class PermissionProxy {
    @Resource
    private RedisUserService redisUserService;

    @Resource
    private ContextUtil contextUtil;

    @Around("@annotation(org.example.annotation.HasPermission) " +
            "|| @annotation(org.example.annotation.Permissions)")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        HasPermission[] aops = getMethod(pjp).getAnnotationsByType(HasPermission.class);
        String userId = contextUtil.getId().toString();
        List<String> aopsList = new ArrayList<>();
        for(HasPermission hasPermission : aops){
            aopsList.add(hasPermission.permission());
        }
        if(redisUserService.judgePermission(userId,aopsList)){
            return pjp.proceed();
        }else{
            throw new AuthException("权限不够");
        }
    }

    protected Method getMethod(ProceedingJoinPoint pjp) {
        Method method = null;
        try {
            MethodSignature ms = (MethodSignature) pjp.getSignature();
            method = pjp.getTarget()
                    .getClass()
                    .getMethod(ms.getName(), ms.getParameterTypes());
        } catch (NoSuchMethodException e) {
            throw new ServerErrorException("快快联系后端，大问题");
        }
        return method;
    }


}
